﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Windows.Forms;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Analysis;   // HVACLoadSpaceType 在这里
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.UI;
using Autodesk.Revit.Attributes;

// --- 使用别名避免冲突 ---
using WinForms = System.Windows.Forms;
using Drawing = System.Drawing;

namespace RevitApiExample // 请确保与您项目的命名空间一致
{
    //====================================================================
    // 主命令类: CreateSpaceTypeCommand
    //====================================================================
    [Transaction(TransactionMode.Manual)]
    [Regeneration(RegenerationOption.Manual)]
    public class CreateSpaceTypeCommand : IExternalCommand
    {
        public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
        {
            UIApplication uiapp = commandData.Application;
            UIDocument uidoc = uiapp.ActiveUIDocument;
            Document doc = uidoc.Document;

            // --- 1. 显示创建窗体 ---
            NewOrEditedSpaceTypeData newTypeData = null; // 使用通用的 DTO
            using (var createForm = new CreateSpaceTypeForm(doc)) // 传入 doc 用于可能的验证
            {
                if (createForm.ShowDialog() == WinForms.DialogResult.OK)
                {
                    newTypeData = createForm.ResultData; // 获取输入的数据（内部单位）
                }
                else
                {
                    return Result.Cancelled; // 用户在创建界面取消
                }
            }

            // --- 2. 最终名称唯一性检查 (在准备创建之前) ---
            if (newTypeData != null)
            {
                bool isNameUnique = !new FilteredElementCollector(doc)
                                        .OfClass(typeof(HVACLoadSpaceType))
                                        .Any(el => el.Name.Equals(newTypeData.Name, StringComparison.OrdinalIgnoreCase));

                if (!isNameUnique)
                {
                    TaskDialog.Show("创建失败", $"名称 '{newTypeData.Name}' 已被另一个空间类型使用。请输入唯一名称。");
                    // 可以考虑重新打开表单让用户修改，或者直接失败
                    return Result.Failed;
                }

                // --- 3. 执行创建和设置属性 ---
                using (Transaction tx = new Transaction(doc, "创建新空间类型"))
                {
                    tx.Start();
                    try
                    {
                        // 创建新的空间类型
                        HVACLoadSpaceType newType = HVACLoadSpaceType.Create(doc, newTypeData.Name);

                        if (newType != null)
                        {
                            // 设置属性 (值已经是从表单传回的内部单位)
                            newType.AreaPerPerson = newTypeData.AreaPerPersonInternal;
                            newType.LightingLoadDensity = newTypeData.LightingLoadDensityInternal;
                            newType.PowerLoadDensity = newTypeData.PowerLoadDensityInternal;
                            newType.SensibleHeatGainPerPerson = newTypeData.SensibleHeatGainPerPersonInternal;
                            newType.LatentHeatGainPerPerson = newTypeData.LatentHeatGainPerPersonInternal;
                            newType.HeatingSetPoint = newTypeData.HeatingSetPointInternal;
                            newType.CoolingSetPoint = newTypeData.CoolingSetPointInternal;
                            // IsPlenum 无法在创建时设置

                            tx.Commit();
                            TaskDialog.Show("成功", $"空间类型 '{newType.Name}' 已成功创建。");
                            return Result.Succeeded;
                        }
                        else
                        {
                            // 创建失败 (很少见，除非名称或其他方面有问题)
                            tx.RollBack();
                            message = $"无法创建名称为 '{newTypeData.Name}' 的空间类型。";
                            TaskDialog.Show("错误", message);
                            return Result.Failed;
                        }
                    }
                    catch (Exception ex)
                    {
                        tx.RollBack();
                        message = $"创建空间类型时出错: {ex.Message}";
                        TaskDialog.Show("错误", message);
                        return Result.Failed;
                    }
                }
            }

            return Result.Failed; // 如果 newTypeData 为 null (理论上不应发生)
        }
    }


    //====================================================================
    // 辅助窗体类: CreateSpaceTypeForm (用于输入新类型信息)
    //====================================================================
    public class CreateSpaceTypeForm : WinForms.Form
    {
        // --- 控件字段 (与 EditSpaceTypeForm 类似) ---
        private WinForms.Label lblName;
        private WinForms.TextBox txtName;
        // IsPlenum 不可设置，可以不显示或显示为固定值
        // private WinForms.Label lblIsPlenum;
        // private WinForms.TextBox txtIsPlenum;
        private WinForms.Label lblAreaPerPerson;
        private WinForms.TextBox txtAreaPerPerson;
        private WinForms.Label lblAreaUnit;
        private WinForms.Label lblLightingLoad;
        private WinForms.TextBox txtLightingLoad;
        private WinForms.Label lblLightingUnit;
        private WinForms.Label lblPowerLoad;
        private WinForms.TextBox txtPowerLoad;
        private WinForms.Label lblPowerUnit;
        private WinForms.Label lblSensibleHeatGain;
        private WinForms.TextBox txtSensibleHeatGain;
        private WinForms.Label lblLatentHeatGain;
        private WinForms.TextBox txtLatentHeatGain;
        private WinForms.Label lblHeatGainUnit;
        private WinForms.Label lblHeatingSetpoint;
        private WinForms.TextBox txtHeatingSetpoint;
        private WinForms.Label lblCoolingSetpoint;
        private WinForms.TextBox txtCoolingSetpoint;
        private WinForms.Label lblTempUnit;
        private WinForms.Button btnOk;
        private WinForms.Button btnCancel;

        // --- 公开属性，用于传递输入的数据 (以内部单位存储) ---
        public NewOrEditedSpaceTypeData ResultData { get; private set; } // 重用 DTO

        // --- 私有字段 ---
        private readonly Document _doc; // 用于验证名称唯一性

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="doc">Revit 文档</param>
        public CreateSpaceTypeForm(Document doc)
        {
            _doc = doc;
            InitializeComponent();
            SetDefaultValues(); // 设置一些合理的默认值
        }

        /// <summary>
        /// 初始化窗体控件 (布局与 EditSpaceTypeForm 非常相似)
        /// </summary>
        private void InitializeComponent()
        {
            // --- 代码与 EditSpaceTypeForm 的 InitializeComponent 非常相似 ---
            // --- 主要区别在于不包含 IsPlenum 控件，且标题不同 ---

            this.lblName = new WinForms.Label();
            this.txtName = new WinForms.TextBox();
            this.lblAreaPerPerson = new WinForms.Label();
            this.txtAreaPerPerson = new WinForms.TextBox();
            this.lblAreaUnit = new WinForms.Label();
            this.lblLightingLoad = new WinForms.Label();
            this.txtLightingLoad = new WinForms.TextBox();
            this.lblLightingUnit = new WinForms.Label();
            this.lblPowerLoad = new WinForms.Label();
            this.txtPowerLoad = new WinForms.TextBox();
            this.lblPowerUnit = new WinForms.Label();
            this.lblSensibleHeatGain = new WinForms.Label();
            this.txtSensibleHeatGain = new WinForms.TextBox();
            this.lblLatentHeatGain = new WinForms.Label();
            this.txtLatentHeatGain = new WinForms.TextBox();
            this.lblHeatGainUnit = new WinForms.Label();
            this.lblHeatingSetpoint = new WinForms.Label();
            this.txtHeatingSetpoint = new WinForms.TextBox();
            this.lblCoolingSetpoint = new WinForms.Label();
            this.txtCoolingSetpoint = new WinForms.TextBox();
            this.lblTempUnit = new WinForms.Label();
            this.btnOk = new WinForms.Button();
            this.btnCancel = new WinForms.Button();

            this.SuspendLayout();

            int top = 15;
            int leftLabel = 15;
            int leftText = 180;
            int leftUnit = 300;
            int spacing = 30;
            int textBoxWidth = 100;
            int formWidth = 420;

            // 名称 (必填)
            this.lblName.Location = new Drawing.Point(leftLabel, top);
            this.lblName.Text = "名称 (*):"; this.lblName.AutoSize = true;
            this.txtName.Location = new Drawing.Point(leftText, top - 2); this.txtName.Size = new Drawing.Size(200, 20); this.txtName.TabIndex = 0;
            top += spacing;

            // IsPlenum 不在此处设置

            // 人均面积
            this.lblAreaPerPerson.Location = new Drawing.Point(leftLabel, top);
            this.lblAreaPerPerson.Text = "人均面积:"; this.lblAreaPerPerson.AutoSize = true;
            this.txtAreaPerPerson.Location = new Drawing.Point(leftText, top - 2); this.txtAreaPerPerson.Size = new Drawing.Size(textBoxWidth, 20); this.txtAreaPerPerson.TabIndex = 1;
            this.lblAreaUnit.Location = new Drawing.Point(leftUnit, top); this.lblAreaUnit.Text = "m²/人"; this.lblAreaUnit.AutoSize = true;
            top += spacing;
            // 照明负荷密度
            this.lblLightingLoad.Location = new Drawing.Point(leftLabel, top);
            this.lblLightingLoad.Text = "照明负荷密度:"; this.lblLightingLoad.AutoSize = true;
            this.txtLightingLoad.Location = new Drawing.Point(leftText, top - 2); this.txtLightingLoad.Size = new Drawing.Size(textBoxWidth, 20); this.txtLightingLoad.TabIndex = 2;
            this.lblLightingUnit.Location = new Drawing.Point(leftUnit, top); this.lblLightingUnit.Text = "W/m²"; this.lblLightingUnit.AutoSize = true;
            top += spacing;
            // 设备负荷密度
            this.lblPowerLoad.Location = new Drawing.Point(leftLabel, top);
            this.lblPowerLoad.Text = "设备负荷密度:"; this.lblPowerLoad.AutoSize = true;
            this.txtPowerLoad.Location = new Drawing.Point(leftText, top - 2); this.txtPowerLoad.Size = new Drawing.Size(textBoxWidth, 20); this.txtPowerLoad.TabIndex = 3;
            this.lblPowerUnit.Location = new Drawing.Point(leftUnit, top); this.lblPowerUnit.Text = "W/m²"; this.lblPowerUnit.AutoSize = true;
            top += spacing;
            // 人员显热
            this.lblSensibleHeatGain.Location = new Drawing.Point(leftLabel, top);
            this.lblSensibleHeatGain.Text = "人员显热:"; this.lblSensibleHeatGain.AutoSize = true;
            this.txtSensibleHeatGain.Location = new Drawing.Point(leftText, top - 2); this.txtSensibleHeatGain.Size = new Drawing.Size(textBoxWidth, 20); this.txtSensibleHeatGain.TabIndex = 4;
            top += spacing;
            // 人员潜热
            this.lblLatentHeatGain.Location = new Drawing.Point(leftLabel, top);
            this.lblLatentHeatGain.Text = "人员潜热:"; this.lblLatentHeatGain.AutoSize = true;
            this.txtLatentHeatGain.Location = new Drawing.Point(leftText, top - 2); this.txtLatentHeatGain.Size = new Drawing.Size(textBoxWidth, 20); this.txtLatentHeatGain.TabIndex = 5;
            this.lblHeatGainUnit.Location = new Drawing.Point(leftUnit, top - (spacing / 2)); this.lblHeatGainUnit.Text = "W/人"; this.lblHeatGainUnit.AutoSize = true;
            top += spacing;
            // 供暖设定点
            this.lblHeatingSetpoint.Location = new Drawing.Point(leftLabel, top);
            this.lblHeatingSetpoint.Text = "供暖设定点:"; this.lblHeatingSetpoint.AutoSize = true;
            this.txtHeatingSetpoint.Location = new Drawing.Point(leftText, top - 2); this.txtHeatingSetpoint.Size = new Drawing.Size(textBoxWidth, 20); this.txtHeatingSetpoint.TabIndex = 6;
            top += spacing;
            // 制冷设定点
            this.lblCoolingSetpoint.Location = new Drawing.Point(leftLabel, top);
            this.lblCoolingSetpoint.Text = "制冷设定点:"; this.lblCoolingSetpoint.AutoSize = true;
            this.txtCoolingSetpoint.Location = new Drawing.Point(leftText, top - 2); this.txtCoolingSetpoint.Size = new Drawing.Size(textBoxWidth, 20); this.txtCoolingSetpoint.TabIndex = 7;
            this.lblTempUnit.Location = new Drawing.Point(leftUnit, top - (spacing / 2)); this.lblTempUnit.Text = "°C"; this.lblTempUnit.AutoSize = true;
            top += spacing + 10;

            // 确定按钮
            this.btnOk.Location = new Drawing.Point(formWidth - 175, top); this.btnOk.Name = "btnOk"; this.btnOk.Size = new Drawing.Size(75, 23); this.btnOk.TabIndex = 8; this.btnOk.Text = "创建"; this.btnOk.UseVisualStyleBackColor = true; // 文本改为“创建”
            this.btnOk.Click += new System.EventHandler(this.BtnOk_Click);

            // 取消按钮
            this.btnCancel.DialogResult = WinForms.DialogResult.Cancel;
            this.btnCancel.Location = new Drawing.Point(formWidth - 90, top); this.btnCancel.Name = "btnCancel"; this.btnCancel.Size = new Drawing.Size(75, 23); this.btnCancel.TabIndex = 9; this.btnCancel.Text = "取消"; this.btnCancel.UseVisualStyleBackColor = true;

            // 窗体设置
            this.AcceptButton = this.btnOk;
            this.CancelButton = this.btnCancel;
            this.ClientSize = new Drawing.Size(formWidth, top + 40);
            this.Controls.Add(this.lblName); this.Controls.Add(this.txtName);
            // 不添加 IsPlenum 控件
            this.Controls.Add(this.lblAreaPerPerson); this.Controls.Add(this.txtAreaPerPerson); this.Controls.Add(this.lblAreaUnit);
            this.Controls.Add(this.lblLightingLoad); this.Controls.Add(this.txtLightingLoad); this.Controls.Add(this.lblLightingUnit);
            this.Controls.Add(this.lblPowerLoad); this.Controls.Add(this.txtPowerLoad); this.Controls.Add(this.lblPowerUnit);
            this.Controls.Add(this.lblSensibleHeatGain); this.Controls.Add(this.txtSensibleHeatGain);
            this.Controls.Add(this.lblLatentHeatGain); this.Controls.Add(this.txtLatentHeatGain); this.Controls.Add(this.lblHeatGainUnit);
            this.Controls.Add(this.lblHeatingSetpoint); this.Controls.Add(this.txtHeatingSetpoint);
            this.Controls.Add(this.lblCoolingSetpoint); this.Controls.Add(this.txtCoolingSetpoint); this.Controls.Add(this.lblTempUnit);
            this.Controls.Add(this.btnOk); this.Controls.Add(this.btnCancel);
            this.FormBorderStyle = WinForms.FormBorderStyle.FixedDialog;
            this.MaximizeBox = false; this.MinimizeBox = false; this.Name = "CreateSpaceTypeForm";
            this.ShowIcon = false; this.ShowInTaskbar = false; this.StartPosition = WinForms.FormStartPosition.CenterParent;
            this.Text = "创建新空间类型"; // 修改标题
            this.ResumeLayout(false);
            this.PerformLayout();
        }

        /// <summary>
        /// 设置输入框的默认值
        /// </summary>
        private void SetDefaultValues()
        {
            // 可以根据需要设置一些常见的默认值
            txtAreaPerPerson.Text = "10.0";
            txtLightingLoad.Text = "8.0";
            txtPowerLoad.Text = "10.0";
            txtSensibleHeatGain.Text = "75";
            txtLatentHeatGain.Text = "55";
            txtHeatingSetpoint.Text = "20";
            txtCoolingSetpoint.Text = "24";
            txtName.Focus(); // 光标定位到名称输入框
        }

        /// <summary>
        /// “确定”/“创建”按钮点击事件：验证、解析、转换单位、设置结果并关闭窗口
        /// </summary>
        private void BtnOk_Click(object sender, EventArgs e)
        {
            // --- 1. 创建结果数据对象 ---
            var data = new NewOrEditedSpaceTypeData(); // 重用 DTO

            // --- 2. 验证和解析输入 ---
            List<string> errors = new List<string>();

            // 名称验证 (非空 + 唯一性)
            data.Name = txtName.Text.Trim();
            if (string.IsNullOrWhiteSpace(data.Name))
            {
                errors.Add("名称不能为空。");
            }
            else
            {
                // 在窗体端进行初步的唯一性检查 (可选，最终检查在命令端进行)
                bool isNameUnique = !new FilteredElementCollector(_doc)
                                    .OfClass(typeof(HVACLoadSpaceType))
                                    .Any(el => el.Name.Equals(data.Name, StringComparison.OrdinalIgnoreCase));
                if (!isNameUnique)
                {
                    errors.Add($"名称 '{data.Name}' 已存在，请输入唯一名称。");
                }
            }

            // 解析数值 (与 EditSpaceTypeForm 相同)
            double areaPerPerson_m2 = 0, lighting_W_m2 = 0, power_W_m2 = 0;
            double sensible_W = 0, latent_W = 0, heating_C = 0, cooling_C = 0;

            if (!double.TryParse(txtAreaPerPerson.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out areaPerPerson_m2) || areaPerPerson_m2 < 0) errors.Add("人均面积必须是有效的非负数字。");
            if (!double.TryParse(txtLightingLoad.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out lighting_W_m2) || lighting_W_m2 < 0) errors.Add("照明负荷密度必须是有效的非负数字。");
            if (!double.TryParse(txtPowerLoad.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out power_W_m2) || power_W_m2 < 0) errors.Add("设备负荷密度必须是有效的非负数字。");
            if (!double.TryParse(txtSensibleHeatGain.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out sensible_W) || sensible_W < 0) errors.Add("人员显热必须是有效的非负数字。");
            if (!double.TryParse(txtLatentHeatGain.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out latent_W) || latent_W < 0) errors.Add("人员潜热必须是有效的非负数字。");
            if (!double.TryParse(txtHeatingSetpoint.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out heating_C)) errors.Add("供暖设定点必须是有效的数字。");
            if (!double.TryParse(txtCoolingSetpoint.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out cooling_C)) errors.Add("制冷设定点必须是有效的数字。");

            if (errors.Count == 0 && cooling_C <= heating_C)
            {
                errors.Add("制冷设定点应高于供暖设定点。");
            }

            if (errors.Count > 0)
            {
                MessageBox.Show("输入无效:\n- " + string.Join("\n- ", errors), "错误", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return; // 保持窗口打开
            }

            // --- 3. 单位转换：从 显示单位 转换为 Revit 内部单位 (与 EditSpaceTypeForm 相同) ---
            try
            {
                // 人均面积 (m² -> ft²)
                data.AreaPerPersonInternal = UnitUtils.ConvertToInternalUnits(areaPerPerson_m2, UnitTypeId.SquareFeet);
                // 照明负荷密度 (W/m² -> W/ft²)
                data.LightingLoadDensityInternal = UnitUtils.ConvertToInternalUnits(lighting_W_m2, UnitTypeId.WattsPerSquareFoot);
                // 设备负荷密度 (W/m² -> W/ft²)
                data.PowerLoadDensityInternal = UnitUtils.ConvertToInternalUnits(power_W_m2, UnitTypeId.WattsPerSquareFoot);
                // 人员显热 (W -> Watts, 无需转换)
                data.SensibleHeatGainPerPersonInternal = sensible_W;
                // 人员潜热 (W -> Watts, 无需转换)
                data.LatentHeatGainPerPersonInternal = latent_W;
                // 供暖设定点 (°C -> K 或 R)
                data.HeatingSetPointInternal = UnitUtils.ConvertToInternalUnits(heating_C, UnitTypeId.Celsius);
                // 制冷设定点 (°C -> K 或 R)
                data.CoolingSetPointInternal = UnitUtils.ConvertToInternalUnits(cooling_C, UnitTypeId.Celsius);

                // --- 4. 设置结果并关闭 ---
                this.ResultData = data;
                this.DialogResult = DialogResult.OK;
                this.Close();
            }
            catch (Exception ex)
            {
                MessageBox.Show($"保存数据时发生单位转换错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }
    }


    //====================================================================
    // 辅助类: NewOrEditedSpaceTypeData (DTO - Data Transfer Object)
    // 可以重用 Edit 命令中的 DTO，或者定义一个新的，这里我们重用
    //====================================================================
    public class NewOrEditedSpaceTypeData // 名称改为更通用或保持原样
    {
        public string Name { get; set; } // 名称

        // 注意：以下属性存储的是 Revit 的【内部单位】值
        public double AreaPerPersonInternal { get; set; } // ft²
        public double LightingLoadDensityInternal { get; set; } // W/ft²
        public double PowerLoadDensityInternal { get; set; } // W/ft²
        public double SensibleHeatGainPerPersonInternal { get; set; } // Watts (根据之前的发现)
        public double LatentHeatGainPerPersonInternal { get; set; } // Watts (根据之前的发现)
        public double HeatingSetPointInternal { get; set; } // K or R
        public double CoolingSetPointInternal { get; set; } // K or R
    }

} // end namespace